/**
 * fileName: SL_YLES_Import_item_barcode_CSV
 * @NApiVersion 2.1
 * @NScriptType Suitelet
 */


/**
 * @author  mark wang
 * @version 1.0.0
 * @date   20221201
 * @description  导入海量CSV文件之 - 【item & barcode】 issue:I63Q59
 */
import {EntryPoints} from 'N/types'
import search = require('N/search')
import file = require('N/file')
import task = require('N/task')
import https = require('N/https')
import record = require('N/record')
import url = require('N/url')
import log = require('N/log')
import redirect = require('N/redirect')
import runtime = require('N/runtime')
import ui = require('N/ui/serverWidget')
import {createImportResultForm, createUI, UI_Form} from "../tools/YLES_UI_FORM";
import {CustomRecordType} from "../tools/YLES_RELATED_RECORDTYPE";
import {Form} from "N/ui/serverWidget";
import {
    dealSearch, getAllItem,
    getCsvFolder,
    ObjectJson
} from "../tools/YLES_SEARCH_TOOL";
import {LookupValueObject} from "N/search";
import {changeImportLog, getCreateScriptDeployment, validateData} from "../tools/YLES_Tool";


//维护界面信息
const UI_GET_INFO: UI_Form = {
    title: 'Import Item&Barcode',
    btn: [
        {id: 'validate_csv', label: 'Validate', functionName: 'validateCSV'},
        {id: 'history_import', label: 'History Import', functionName: 'historyImport'},
    ],
    group: [],
    bodyField: [
        {id: 'upload_file', label: 'Select CSV File', type: ui.FieldType.FILE, displayType: ui.FieldDisplayType.NORMAL},
        {id: 'submit_operate', label: 'Operate', type: ui.FieldType.TEXT, displayType: ui.FieldDisplayType.HIDDEN},
        {id: 'history_link', label: 'History', type: ui.FieldType.INLINEHTML, displayType: ui.FieldDisplayType.HIDDEN},
        {id: 'import_log', label: 'Import Log', type: ui.FieldType.TEXT, displayType: ui.FieldDisplayType.HIDDEN},
        {id: 'params_args', label: 'Params', type: ui.FieldType.LONGTEXT, displayType: ui.FieldDisplayType.HIDDEN},
    ],
    lineField: [],
}

let req: https.ServerRequest, res: https.ServerResponse, params: any;

export function onRequest(cxt: EntryPoints.Suitelet.onRequestContext) {
    req = cxt.request;
    res = cxt.response;
    params = req.parameters;
    let form: Form | undefined;
    if (req.method === 'GET') {
        if (!params.logId) {
            //1.create upload form
            form = createUI(UI_GET_INFO);
            log.debug({title: 'params', details: params});
            form.addSubmitButton({label: 'submit'}).isHidden = true;
            form.getField({id: 'history_link'}).defaultValue = getHistoryLink();
            form.getField({id: 'params_args'}).defaultValue = JSON.stringify(params);
            form.clientScriptModulePath = './CS_YLES_Import_item_barcode_CSV.js';
        } else {
            //create validate form
            form = createValidateForm(params.logId);
        }

        if (form) {
            res.writePage(form);
        }
    } else if (req.method === 'POST') {
        log.debug({title: 'POST enter：', details: 'post'});
        if (params.params_args) params = JSON.parse(params.params_args);
        if (req.parameters.submit_operate.indexOf('validate') > -1) {
            validateCreate();
        } else if (['import','import_generate'].includes(req.parameters.submit_operate)) {
            //create item&barcode
            startImportTask(req.parameters.import_log);
            res.sendRedirect({
                identifier: 'customscript_yles_import_csv_history_sl',
                id: 'customdeploy_yles_import_csv_history_sl',
                type: 'suitelet',
                parameters: {
                    'logId': req.parameters.import_log
                }
            });
        }
    }
}

//执行异步脚本
function startImportTask(logId: number) {
    try {
        let t = task.create({taskType: task.TaskType.MAP_REDUCE});
        t.scriptId = 'customscript_yles_import_item_barcode_mr';
        t.deploymentId = 'customdeploy_yles_import_item_barcode_mr';
        t.params = {"custscript_yles_import_item_barcode_log": logId};
        t.submit();
        log.debug({title: 'startImportTask', details: 'success'});

        //修改导入日志状态
        let rec = record.load({type: CustomRecordType().IMPORT_ITEM_BARCODE_LOG, id: logId});
        rec.setValue({fieldId: 'custrecord_yles_status', value: 3}); // 导入中 In Progress
        rec.setValue({fieldId: 'custrecord_yles_operate', value: req.parameters.submit_operate});
        rec.save({ignoreMandatoryFields:true});
    } catch (e) {
        log.error({title: 'startImportTask error', details: e});
    }
}

//create valid form
function createValidateForm(importLog: string): Form | undefined {
    const pageInfo = pageToHistory(importLog);
    if (pageInfo.isToPage) return;

    const form = ui.createForm({title: UI_GET_INFO.title});
    form.addSubmitButton({label: 'submit'}).isHidden = true;
    form.clientScriptModulePath = './CS_YLES_Import_item_barcode_CSV.js';
    for (const bv of UI_GET_INFO.btn) {
        form.addButton(bv);
    }
    //form.addButton({id: 'export', label: 'Export Data', functionName: 'exportCSV'});
    //form.addButton({id: 'history_log', label: 'History Log', functionName: 'historyLog'});

    //只有在初始状态为未开始，才做CSV校验
    const logRec = record.load({type: CustomRecordType().IMPORT_ITEM_BARCODE_LOG, id: importLog});
    if (pageInfo.sts != '2') {
        //add field
        form.addFieldGroup({id:'imp_group',label:'Import'});
        UI_GET_INFO.bodyField.map(v => {
            const fd = form.addField({id: v.id, type: v.type, label: v.label,container:v.id == 'upload_file' ? undefined : 'imp_group'});
            if (v.displayType) {
                fd.updateDisplayType({displayType: v.displayType});
            }
            if (v.id == 'import_log') {
                fd.defaultValue = importLog;
            }
        });

        //创建上传CSV字段
        form.insertField({field:form.getField({id:'history_link'}),nextfield:'submit_operate'});
        form.insertField({field:form.getField({id:'upload_file'}),nextfield:'history_link'});
        form.getField({id:'history_link'}).defaultValue = getHistoryLink() + '<br/><br/><br/>';
        form.getField({id: 'params_args'}).defaultValue = JSON.stringify(params);
    }else {
        form.getButton({id:'validate_csv'}).isHidden = true;
    }
    //获取校验等级
    const ckLevel = logRec.getValue('custrecord_yles_operate') as string;
    if (pageInfo.sts == '1') {
        const csvFile = file.load(logRec.getValue('custrecord_yles_csvfile') as string);
        //导入校验数据
        const validateRes = validateData(csvFile);
        log.debug('validateRes',validateRes);

        //更新导入日志
        changeImportLog(validateRes, importLog);

        if (validateRes.successLine > 0) {
            if (ckLevel === 'validate') {
                form.addButton({id: 'update', label: 'Submit', functionName: 'updateCSV'});
            }
        }
    }else {
        //是否存在ck success file
        const ckSuccessFile = logRec.getValue('custrecord_yles_imp_success_csv') as string;
        if (ckSuccessFile && ckLevel === 'validate') {
            form.addButton({id: 'update', label: 'Submit', functionName: 'updateCSV'});
        }
    }

    //创建导入详情界面
    createImportResultForm(params.logId,form);
    return form;
}

//获取历史导入记录
function getHistoryLink() {
    let link = url.resolveScript({
        scriptId: 'customscript_yles_import_csv_history_sl',
        deploymentId: 'customdeploy_yles_import_csv_history_sl'
    });
    let html = `<br/><a href="${link}" target="_blank">Click here to view import history</a>`;
    return html;
}

//界面跳转
function pageToHistory(importLog:string) {
    //检查若初始状态不是Not Start,则重定向至history界面
    const sts = ((search.lookupFields({
        type: CustomRecordType().IMPORT_ITEM_BARCODE_LOG,
        id: importLog,
        columns: ['custrecord_yles_status']
    })['custrecord_yles_status'] as LookupValueObject[])[0] || {}).value;
    log.debug({title: 'sts', details: sts});
    if (['3','5','6'].includes(sts)) {
        redirect.toSuitelet({
            scriptId: 'customscript_yles_import_csv_history_sl',
            deploymentId: 'customdeploy_yles_import_csv_history_sl',
            parameters: {logId: importLog}
        });
        return {isToPage:true,sts};
    }
    return {isToPage:false,sts};
}


//校验csv
function validateCreate() {
    log.debug({title: 'validateCreate PARAMS：', details: params});
    const csvFile = req.files.upload_file;
    const fileName = JSON.parse(JSON.stringify(csvFile)).name;
    csvFile.encoding = file.Encoding.GB18030;//UTF_8
    const now = new Date();
    const fId = getCsvFolder();
    csvFile.name = 'ibCsv_' + now.getTime();

    if (fId) {
        csvFile.folder = fId;
        const sd = (new Date).getTime();
        const csvLineNo = getFileLineNo(csvFile);

        if (csvLineNo == 0) {
            const tUrl = url.resolveScript({
                scriptId: 'customscript_yles_csv_item_barcode_im_sl',
                deploymentId: 'customdeploy_yles_csv_item_barcode_im_sl'
            })
            res.write(`<script type='text/javascript'>alert("Empty CSV! Upload and Check again.");window.onbeforeunload = null;window.location.href="${tUrl}";</script>`);
            return;
        }
        const csvId = csvFile.save();
        const ed = (new Date).getTime();
        log.debug({title: '保存CSV耗费的时间：', details: ed - sd});
        // const importLog = createLog(createImportCsvFile(csvFile),fileName);
        log.debug({title: 'csvFile.size：', details: csvFile.size});

        //大于10M。异步校验
        let importLog = 0;
        if (csvFile.size >= 5 * 1048576) {
            importLog = createLog(csvId,fileName,csvLineNo,'2');

            //启动校验程序
            startCSVCheck(importLog);
        }else {
            importLog = createLog(csvId,fileName,csvLineNo,'1');
        }
        log.debug({title: 'validateCreate importLog', details: importLog});
        res.sendRedirect({
            identifier: 'customscript_yles_csv_item_barcode_im_sl',
            id: 'customdeploy_yles_csv_item_barcode_im_sl', type: 'suitelet',
            parameters: {'logId': importLog}
        });
    }else {
        throw '获取文件夹失败，请返回重新操作';
    }
}

//执行异步校验 - 一个员工当前只能有一个校验程序在执行
function startCSVCheck(logId: number) {
    const depId = 'customdeploy_yles_check_csv_mr' +runtime.getCurrentUser().id;
    getCreateScriptDeployment({scriptId: 'customscript_yles_check_csv_mr', depId: depId});
    try {
        const ts = task.create({
            taskType: task.TaskType.MAP_REDUCE,
            scriptId: 'customscript_yles_check_csv_mr',
            deploymentId: depId,
            params: {
                custscript_yles_check_item_barcode_log: logId
            }
        });
        ts.submit();
    } catch (e) {
        log.error({title: 'runMapReduce error', details: e});
        record.delete({type: CustomRecordType().IMPORT_ITEM_BARCODE_LOG, id: logId});
        //@ts-ignore
        throw `当前用户已有正在执行的校验程序，请稍后再试.`;
    }
}

//获取CSV文件总条数
function getFileLineNo(csvFile:file.File) {
    //循环CSV数组,总条数
    let lines = 0;
    const iterator = csvFile.lines.iterator();
    iterator.each(function () {return false;});
    iterator.each(function (line:{value:string}) {
        lines++;
        return true;
    });

    /*const sessionObj = runtime.getCurrentSession(); //sessionObj is a runtime.Session object
    //校验的条数
    sessionObj.set({
        name: String(req.parameters.now_time + '_total'),
        value: lines.toString()
    });*/
    return lines;
}

//创建导入的CSV文件
function createImportCsvFile(uploadFile:file.File) {
    //创建校验错误的CSV文件
    const impCsv = file.create({
        fileType: file.Type.CSV,
        name: 'ibCsv_' + new Date().getTime(),
        folder: uploadFile.folder
    });
    impCsv.encoding = 'GB18030';//file.Encoding.GB18030;//UTF_8
    //循环CSV数组
    const iterator = uploadFile.lines.iterator();
    iterator.each(function (line:{value:string}) {
        const lineValues = line.value.split('\t');
        const item = (lineValues[0] || '').trim();
        const barcode = (lineValues[1] || '').trim();
        // const item = valToCsv((lineValues[0] || '').trim());
        // const barcode = valToCsv((lineValues[1] || '').trim());


        impCsv.appendLine({
            value: `${item},${barcode}`
        });
        return true;
    });
    const impCsvId = impCsv.save();
    return impCsvId;
}

//将逗号以及引号转义
function valToCsv(strVal: string) {
    if (strVal.indexOf(",") > -1) {
        if (strVal.indexOf("\"") > -1) {
            strVal = strVal.replace(/"/g, `""`);
        }
        //将逗号转义
        strVal = "\"" + strVal + "\"";
    }
    return strVal;
}

//创建导入日志
function createLog(fId: string | number,fileName:string,csvLineNo:number,sts:string) {
    const rec = record.create({type: CustomRecordType().IMPORT_ITEM_BARCODE_LOG})
    rec.setValue({fieldId: 'custrecord_yles_csvfile', value: fId});
    rec.setValue({fieldId: 'custrecord_yles_csv_name', value: fileName});
    rec.setValue({fieldId: 'custrecord_yles_status', value: sts});
    rec.setValue({fieldId: 'custrecord_yles_total_csv_line_no', value: csvLineNo});
    rec.setValue({fieldId: 'custrecord_yles_imp_vali_time_flag', value: new Date().getTime().toString()});
    rec.setValue({fieldId: 'custrecord_yles_operate', value: req.parameters.submit_operate});
    const logId = rec.save({ignoreMandatoryFields:true});
    return logId;
}
